package main

import (
	"context"
	"crypto/tls"
	"github.com/quic-go/quic-go"
	"io"
	"log"
	"sync"
	"time"
)

const (
	addr = "localhost:4242"
	//keyFile  = "/Users/edy/Desktop/8128616_barrage.houry.top.key"
	//certFile = "/Users/edy/Desktop/8128616_barrage.houry.top.pem"

	//keyFile := "/Users/edy/webtransport.go+1-key.pem"
	keyFile = "E:\\google\\9227282_webtransport.houry.top_other\\9227282_webtransport.houry.top.key"

	//certFile := "/Users/edy/webtransport.go+1.pem"
	certFile = "E:\\google\\9227282_webtransport.houry.top_other\\9227282_webtransport.houry.top.pem"

	KEY = "trace_id"
)

var connMap sync.Map

func main() {

	listener, err := quic.ListenAddr(addr, generateTLSConfig(), nil)
	if err != nil {
		log.Println("err1", err)
		return
	}
	go startServer(listener)
	go startMonitor()
	go receiveData()

	go func() {
		for {
			time.Sleep(time.Second)
			sendData([]byte("hello"))
		}
	}()

	select {}

}

func startServer(listener quic.Listener) {
	log.Println("启动quic服务监听")
	for {
		conn, err := listener.Accept(context.Background())
		if err != nil {
			log.Println("err2", err)
			return
		}
		connMap.Store(conn, conn)
	}
}

func receiveData() {
	log.Println("开启数据接收服务")
	for {
		connMap.Range(func(key, value any) bool {
			connection := value.(quic.Connection)
			stream, err := connection.AcceptStream(connection.Context())
			if err != nil {
				log.Println("开启流通道失败:", err)
				connMap.Delete(key)
			} else {
				bytes, err := io.ReadAll(stream)
				if err != nil {
					log.Println("接收数据失败:", err)
					connMap.Delete(key)
				} else {
					log.Println("接收到数据：", string(bytes))
				}
			}
			stream.Close()
			return true
		})
	}
}

func sendData(byteData []byte) {
	connMap.Range(func(key, value any) bool {
		connection := value.(quic.Connection)
		stream, err := connection.OpenStreamSync(connection.Context())
		if err != nil {
			log.Println("开启流通道失败:", err)
			connMap.Delete(key)
		} else {
			_, _ = stream.Write(byteData)
			_ = stream.Close()
		}
		return true
	})

}

func startMonitor() {
	log.Println("开始监控连接信息")
	for {
		time.Sleep(time.Second)
		connMap.Range(func(key, value any) bool {
			connection := value.(quic.Connection)
			if connection.Context().Err() != nil {
				connMap.Delete(key)
			}
			return true
		})
	}
}

func generateTLSConfig() *tls.Config {
	pair, err := tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		log.Println("errrrr", err)
		return nil
	}
	return &tls.Config{
		Certificates: []tls.Certificate{pair},
		NextProtos:   []string{"barrage.houry.top"},
	}
}
